package com.jushu.storbox.view.pulltorefresh;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.LinearLayout;
import android.widget.ScrollView;

import com.jushu.storbox.R;
import com.jushu.storbox.ShareDriveApplication;
import com.jushu.storbox.util.LogUtil;

public class PullDownScrollView extends LinearLayout {
	private int resetSpeed = 25;
	public static int RESETFAST = 25;
	public static int RESETNORMAL = 20;
	public static int RESETSLOW = 15;

	private static final String TAG = "PullDownScrollView";

	private int refreshTargetTop = -60;
	private int headContentHeight;

	private RefreshListener refreshListener;

	private RotateAnimation animation;
	private RotateAnimation reverseAnimation;

	private final static int RATIO = 2;
	private int preY = 0;
	private boolean isElastic = false;
	private int startY;
	private int state;
	private boolean preY_flag = true;

	private IPullDownElastic mElastic;

	private boolean canScroll = true;

	private Context context;

	public boolean isCanScroll() {
		return canScroll;
	}

	public void setCanScroll(boolean canScroll) {
		this.canScroll = canScroll;
	}

	public PullDownScrollView(Context context) {
		super(context);
		this.context = context;
		init();
	}

	public PullDownScrollView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		ShareDriveApplication.getInstance().setScrolling(false);
		init();
	}

	private void init() {
		animation = new RotateAnimation(0, -180,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		animation.setInterpolator(new LinearInterpolator());
		animation.setDuration(250);
		animation.setFillAfter(true);

		reverseAnimation = new RotateAnimation(-180, 0,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		reverseAnimation.setInterpolator(new LinearInterpolator());
		reverseAnimation.setDuration(200);
		reverseAnimation.setFillAfter(true);
	}

	/**
	 * @param listener
	 */
	public void setRefreshListener(RefreshListener listener) {
		this.refreshListener = listener;
	}

	/**
	 * @param elastic
	 */
	public void setPullDownElastic(IPullDownElastic elastic) {
		mElastic = elastic;

		headContentHeight = mElastic.getElasticHeight();
		refreshTargetTop = -headContentHeight;
		LayoutParams lp = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, headContentHeight);
		lp.topMargin = refreshTargetTop;
		addView(mElastic.getElasticLayout(), 0, lp);
	}

	/**
	 * @param pullToRefresh
	 * @param releaseToRefresh
	 * @param refreshing
	 */
	public void setRefreshTips(String pullToRefresh, String releaseToRefresh,
			String refreshing) {
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		return super.dispatchTouchEvent(ev);
	}

	/*
	 * @see
	 * android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)
	 */
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		LogUtil.d(TAG, "onInterceptTouchEvent");
		printMotionEvent(ev);
		Log.d("inanim", "is anim showing:"
				+ ShareDriveApplication.getInstance().isAnimShowing());
		if (ShareDriveApplication.getInstance().isCanMove()
				|| ShareDriveApplication.getInstance().isAnimShowing()) {

			return true;
		} else {
			return super.onInterceptTouchEvent(ev);
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		LogUtil.d(TAG, "onTouchEvent");
		printMotionEvent(event);
		handleHeadElastic(event);
		return true;
	}

	private void handleHeadElastic(MotionEvent event) {
		if (refreshListener != null && mElastic != null) {
			switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:
				LogUtil.i(TAG, "down");
				preY = (int) event.getY();
				Log.d("pulltore", "preY[ACTION_DOWN]:"+preY);
				break;
			case MotionEvent.ACTION_CANCEL:
				// finishRefresh();
				// isElastic = false;
				// break;
				preY_flag = true;
			case MotionEvent.ACTION_UP:
				preY_flag = true;
				LogUtil.i(TAG, "up");
				LogUtil.d(TAG, "isElastic:" + isElastic + " canScroll:"
						+ canScroll() + " ev.getY() - preY:"
						+ (event.getY() - preY));
				if (state != IPullDownElastic.REFRESHING && isElastic) {
					if (state == IPullDownElastic.DONE) {
						setMargin(refreshTargetTop);
					}
					if (state == IPullDownElastic.PULL_To_REFRESH) {
						state = IPullDownElastic.DONE;
						setMargin(refreshTargetTop);
						changeHeaderViewByState(state, false);
						LogUtil.i(TAG, "from pull down to fresh, then done");
					}
					if (state == IPullDownElastic.RELEASE_To_REFRESH) {
						// Animation animation =
						// AnimationUtils.loadAnimation(getContext(),
						// R.anim.pull_out_to_top);
						// this.startAnimation(animation);
						// mElastic.getElasticLayout().startAnimation(animation);
						state = IPullDownElastic.REFRESHING;
						setMargin(0);
						changeHeaderViewByState(state, false);
						onRefresh();
						// state = IPullDownElastic.DONE;
						LogUtil.i(TAG, "from relase fresh to done");
					}

				}
				if (IPullDownElastic.DONE == state) {
					ShareDriveApplication.getInstance().setScrolling(false);
				}
				isElastic = false;
				break;
			case MotionEvent.ACTION_MOVE:
				if(preY_flag){
					preY = (int) event.getY();
					preY_flag = false;
				}
				LogUtil.i(TAG, "move");
//				Log.d("pulltore", "preY[ACTION_MOVE]:"+preY);
//				Log.d("pulltore", "!isElastic:"+!isElastic);
//				Log.d("pulltore", "isCanScroll():"+isCanScroll());
//				Log.d("pulltore", "event.getY() | preY | -refreshTargetTop "+ event.getY() + "|" + preY + "|" +-refreshTargetTop );
//				Log.d("pulltore", "refreshListener:"+refreshListener);
//				Log.d("pulltore", "mElastic:"+mElastic);
				if (!isElastic
						&& isCanScroll()
						&& canScroll()
						&& (int) event.getY() - preY >= -refreshTargetTop
								/ (3 * RATIO) && refreshListener != null
						&& mElastic != null) {

					isElastic = true;
					startY = (int) event.getY();
					LogUtil.i(TAG, "startY:" + startY);
				}
				int tempY = (int) event.getY();
				if (!ShareDriveApplication.getInstance().isScrolling()) {
					ShareDriveApplication.getInstance().setScrolling(true);
				}
				if (state != IPullDownElastic.REFRESHING && isElastic) {
					if (state == IPullDownElastic.RELEASE_To_REFRESH) {
						if (((tempY - startY) / RATIO < -refreshTargetTop)
								&& (tempY - startY) > 0) {
							state = IPullDownElastic.PULL_To_REFRESH;
							changeHeaderViewByState(state, true);
						} else if (tempY - startY <= 0) {
							state = IPullDownElastic.DONE;
							changeHeaderViewByState(state, false);
						}
					}
					if (state == IPullDownElastic.DONE) {
						if (tempY - startY > 0) {
							state = IPullDownElastic.PULL_To_REFRESH;
							changeHeaderViewByState(state, false);
						}
					}
					if (state == IPullDownElastic.PULL_To_REFRESH) {
						if ((tempY - startY) / RATIO >= -refreshTargetTop) {
							state = IPullDownElastic.RELEASE_To_REFRESH;
							changeHeaderViewByState(state, false);
						} else if (tempY - startY <= 0) {
							state = IPullDownElastic.DONE;
							changeHeaderViewByState(state, false);
						}
					}
					if (tempY - startY > 0) {
						setMargin((tempY - startY) / 2 + refreshTargetTop);
					}
				}
				break;
			}
		}
	}

	/**
     * 
     */
	public void setMargin(int top) {
		LinearLayout.LayoutParams lp = (LayoutParams) mElastic
				.getElasticLayout().getLayoutParams();
		lp.topMargin = top;
		mElastic.getElasticLayout().setLayoutParams(lp);
		mElastic.getElasticLayout().invalidate();
	}

	public void changeHeaderViewByState(int state, boolean isBack) {

		mElastic.changeElasticState(state, isBack);
		switch (state) {
		case IPullDownElastic.RELEASE_To_REFRESH:
			mElastic.showArrow(View.VISIBLE);
			mElastic.showProgressBar(View.GONE);
			mElastic.showLastUpdate(View.VISIBLE);
			mElastic.setTips(context
					.getString(R.string.pull_to_refresh_release_label));

			mElastic.clearAnimation();
			mElastic.startAnimation(animation);
			break;
		case IPullDownElastic.PULL_To_REFRESH:
			mElastic.showArrow(View.VISIBLE);
			mElastic.showProgressBar(View.GONE);
			mElastic.showLastUpdate(View.VISIBLE);
			mElastic.setTips(context
					.getString(R.string.pull_to_refresh_pull_label));

			mElastic.clearAnimation();

			if (isBack) {
				mElastic.startAnimation(reverseAnimation);
			}
			break;
		case IPullDownElastic.REFRESHING:
			mElastic.showArrow(View.GONE);
			mElastic.showProgressBar(View.VISIBLE);
			mElastic.showLastUpdate(View.GONE);
			mElastic.setTips(context
					.getString(R.string.pull_to_refresh_from_bottom_refreshing_label));

			mElastic.clearAnimation();
			break;
		case IPullDownElastic.DONE:
			mElastic.showArrow(View.GONE);
			mElastic.showProgressBar(View.GONE);
			mElastic.showLastUpdate(View.GONE);
			mElastic.setTips(context
					.getString(R.string.pull_to_refresh_refreshing_complete));
			mElastic.clearAnimation();
			// arrowImageView.setImageResource(R.drawable.goicon);
			// lastUpdatedTextView.setVisibility(View.VISIBLE);
			LogUtil.i(TAG, "current，done");
			break;
		}
	}

	private void onRefresh() {
		// downTextView.setVisibility(View.GONE);
		// scroller.startScroll(0, i, 0, 0 - i);
		// invalidate();
		if (refreshListener != null && ShareDriveApplication.getInstance()
				.getWifiController().getNetworkState()) {
			refreshListener.onRefresh(this);
		} else {
			state = IPullDownElastic.DONE;
			changeHeaderViewByState(state, false);
			mElastic.showArrow(View.VISIBLE);
			mElastic.showLastUpdate(View.VISIBLE);
			Message msg = new Message();
			msg.arg1 = 0;
			msg.what = 0;
			handler.sendMessageDelayed(msg, 1000);
		}
	}

	/**
     * 
     */
	@Override
	public void computeScroll() {
		// if (scroller.computeScrollOffset()) {
		// int i = this.scroller.getCurrY();
		// LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
		// this.refreshView
		// .getLayoutParams();
		// int k = Math.max(i, refreshTargetTop);
		// lp.topMargin = k;
		// this.refreshView.setLayoutParams(lp);
		// this.refreshView.invalidate();
		// invalidate();
		// }
	}

	public void setLastUpdateTime(String text) {
		if (text != null) {
			mElastic.setLastUpdateText(text);
		}
	}

	/**
	 * @param text
	 */
	public void finishRefresh() {
		if (mElastic == null) {
			LogUtil.e(TAG, "finishRefresh mElastic:" + mElastic);
			return;
		}
		if (state == IPullDownElastic.DONE) {
			LogUtil.e(TAG, "==> finishRefresh state has already done");
		}
		state = IPullDownElastic.DONE;

		changeHeaderViewByState(state, false);

		mElastic.showArrow(View.VISIBLE);
		mElastic.showLastUpdate(View.VISIBLE);

		int i = 0;
		Message msg = new Message();
		msg.what = 0;
		msg.arg1 = i;
		handler.sendMessageDelayed(msg, 800);
		// scroller.startScroll(0, i, 0, refreshTargetTop);
		// invalidate();
	}

	private boolean canScroll() {
		View childView;
		if (getChildCount() > 1) {
			childView = this.getChildAt(1);
			if (childView instanceof AbsListView) {
				int top = ((AbsListView) childView).getChildAt(0).getTop();
				int pad = ((AbsListView) childView).getListPaddingTop();
				if ((Math.abs(top - pad)) < 3
						&& ((AbsListView) childView).getFirstVisiblePosition() == 0) {
					return true;
				} else {
					return false;
				}
			} else if (childView instanceof ScrollView) {
				if (((ScrollView) childView).getScrollY() == 0) {
					return true;
				} else {
					return false;
				}
			}

		}
		return canScroll(this);
	}

	/**
	 * @param view
	 * @return
	 */
	public boolean canScroll(PullDownScrollView view) {
		return false;
	}

	private void printMotionEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			LogUtil.d(TAG, "down");
			break;
		case MotionEvent.ACTION_MOVE:
			LogUtil.d(TAG, "move");
			break;
		case MotionEvent.ACTION_UP:
			LogUtil.d(TAG, "up");
		default:
			break;
		}
	}

	public interface RefreshListener {
		public void onRefresh(PullDownScrollView view);
	}

	@SuppressLint("HandlerLeak")
	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {

			switch (msg.what) {

			case 0:

				int i = msg.arg1;
				if (i > refreshTargetTop) {
					setMargin(i);
					i = i - resetSpeed;
					Message message1 = new Message();
					message1.what = 0;
					message1.arg1 = i;
					handler.sendMessage(message1);
				} else {
					setMargin(refreshTargetTop);
					ShareDriveApplication.getInstance().setScrolling(false);
				}
				break;
			case 1:
				break;
			default:
				break;
			}
		};
	};

	public void setRestSpeed(int speed) {
		resetSpeed = speed;
	}
}
